﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using br.com.SistemaChamados.QueryManager.Utils;
using br.com.SistemaChamados.QueryManager.ReaderParser;
using System.Reflection;
using br.com.SistemaChamados.QueryManager.Core;

namespace br.com.SistemaChamados.QueryManager.ReaderParser
{
    public class DataParser
    {

        private Type _aType;
        private IDataReader _aReader;

        public DataParser()
        {
            //Empty Constructor
        }

        public DataParser(Type _type, IDataReader _reader)
        {
            this._aType = _type;
            this._aReader = _reader;
        }

        public List<object> processAndConvertIDataReader()
        {
            List<object> resultList = new List<object>();
            Type[] arrayFieldTypes = getFieldTypes();
            string[] arrayFieldNames = getFieldNames();
            while (_aReader.Read())
            {
                Object obj = ReflectionUtils.createAnObjectFromType(_aType);
                for (int i = 0; i < arrayFieldTypes.Length; i++)
                {
                    PropertyInfo propertyInfo = ReflectionUtils.getPropertyByName(_aType, _aType.GetProperties()[i].Name);
                    Type fieldType = arrayFieldTypes[i];
                    if (_aReader[i] != null)
                    {
                        if (isAParseableType(propertyInfo.PropertyType.FullName))
                        {
                            propertyInfo.SetValue(obj, DataConverter.bindData(_aReader, i, fieldType), null);
                        }
                        else
                        {
                            Type typeOfCompositeObject = propertyInfo.PropertyType;
                            Object compositeObj = ReflectionUtils.createAnObjectFromType(typeOfCompositeObject);
                            PropertyInfo compositePropertyInfo = ReflectionUtils.getPropertyByName(typeOfCompositeObject,
                                                                                                    QueryManagerConstants.IDENTIFIER_PROPERTY_NAME);
                            compositePropertyInfo.SetValue(compositeObj,
                                                           DataConverter.bindData(_aReader, i, fieldType), null);
                            propertyInfo.SetValue(obj,
                                   compositeObj, null);

                        }
                    }
                }
                resultList.Add(obj);
                obj = null;
            }
            return resultList;
        }

        private Type[] getFieldTypes()
        {
            Type[] fieldTypes = new Type[_aReader.FieldCount];
            for (int i = 0; i < _aReader.FieldCount; i++)
            {
                fieldTypes[i] = _aReader.GetFieldType(i);
            }
            return fieldTypes;
        }

        private string[] getFieldNames()
        {
            string[] fieldNames = new string[_aReader.FieldCount];
            for (int i = 0; i < _aReader.FieldCount; i++)
            {
                fieldNames[i] = _aReader.GetSchemaTable().Columns[i].ColumnName;
            }
            return fieldNames;
        }

        private bool isAParseableType(string typeName)
        {
            for (int i = 0; i < QueryManagerConstants.PARSEABLE_TYPES.Count(); i++ )
            {
                if (QueryManagerConstants.PARSEABLE_TYPES[i].Equals(typeName))
                {
                    return true;
                }
            }
            return false;
        }
    }
}